{
	/*
	 *   以abstract开头的类是抽象类，
	 *       抽象类和其他类区别不大，只是不能用来创建对象
	 *       抽象类就是专门用来被继承的类
	 *
	 *       抽象类中可以添加抽象方法
	 */

	// 定义一个Animal抽象类
	abstract class Animal {
		name: string;
		age: number;

		constructor(name: string, age: number) {
			this.name = name;
			this.age = age;
		}

		// 定义一个抽象方法
		// 抽象方法使用 abstract开头，没有方法体
		// 抽象方法只能定义在抽象类中，子类必须对抽象方法进行重写
		abstract sayHello(): void;
	}

	const animal: Animal = {
		name: "",
		age: 0,
		sayHello: function (): void {
			throw new Error("Function not implemented.");
		}
	}

	class Dog extends Animal {
		// 定义实例属性
		species: string;

		// 如果在子类中写了构造函数，在子类构造函数中"必须"对父类的构造函数进行调用
		constructor(name: string, age: number, species: string) {
			// 使用super调用父类的构造函数，super就表示当前类的父类
			super(name, age);
			this.species = species;
		}

		sayHello() {
			console.log('汪汪汪~');
		}

		run() {
			console.log(`${this.name}在跑`);
		}
	}

	const obj: Dog = {
		species: "",
		sayHello: function (): void {
			throw new Error("Function not implemented.");
		},
		run: function (): void {
			throw new Error("Function not implemented.");
		},
		name: "",
		age: 0
	}

	class Cat extends Animal {
		sayHello(): void {
			console.log('喵喵喵');
		}
		run() {
			console.log(`${this.name}在跑`);
		}
	}

	// const animal = new Animal(); //报错：无法创建抽象类的实例

	const dog = new Dog('小黑', 3, '柯基');
	const cat = new Cat('小黄', 2);
	console.log(dog);
	dog.sayHello();
	dog.run();

	console.log(cat);
	cat.sayHello();
	cat.run();
}
